package com.zzzyh.forumsystemclient.filter;

import com.alibaba.fastjson.JSON;
import com.zzzyh.forumsystemclient.common.AppResult;
import com.zzzyh.forumsystemclient.common.ResultCode;
import com.zzzyh.forumsystemclient.exception.AppException;
import com.zzzyh.forumsystemclient.model.LoginUser;
import com.zzzyh.forumsystemclient.services.ITokenBlacklistService;
import com.zzzyh.forumsystemclient.utils.JwtUtils;
import com.zzzyh.forumsystemclient.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 郑雨杭
 * @create 2025/4/25 - 18:39
 */
@Component
@Slf4j
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    private final String TOKEN_HEADER = "Authorization";

    @Autowired
    private ITokenBlacklistService tokenBlacklistService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String uri = request.getRequestURI();
        log.info("用户{}请求接口{}",request.getRemoteAddr(),uri);
        if (uri.equals("/user/login") || uri.equals("/user/createUser") ||
                uri.startsWith("/sys/config")||
                uri.startsWith("/auth") ||
        uri.endsWith("/register")  ||
        uri.equals("/api/sendEmailCode") ||
        uri.equals("/api/usernameIsUnique") ||
        uri.equals("/api/email/forgot") ||
        uri.startsWith("/websocket") ||
        uri.startsWith("/api/article") ||
        uri.equals("/api/getNotice")){
            filterChain.doFilter(request,response);
            return;
        }
        try{
            vaildateToken(request);
        } catch (Exception e) {
            // 处理 JWT 验证失败的情况
            response.setContentType("application/json;charset=UTF-8");
            ServletOutputStream outputStream = response.getOutputStream();
//            String jsonString = JSON.toJSONString(new AppException(e.getMessage()));
//             String jsonString = JSON.toJSONString(AppResult.failed(e.getMessage()));
            AppResult<Object> failed = AppResult.failed(ResultCode.FAILED_JWT_ERROR);
            if(StringUtil.isEmpty(e.getMessage()))
                failed.setMessage(e.getMessage());
             String jsonString = JSON.toJSONString(failed);
            outputStream.write(jsonString.getBytes("UTF-8"));
            outputStream.flush();
            outputStream.close();
//            throw new AppException(ResultCode.FAILED_JWT_ERROR);
            return;
        }

        filterChain.doFilter(request,response);

    }

    private void vaildateToken(HttpServletRequest request){
        String token = request.getHeader(TOKEN_HEADER);
        log.info("用户{}请求接口{}",token,request.getRequestURI());

        if(token == null){
//            throw new AppException("token为空");
            throw new AppException(ResultCode.FAILED_JWT_ERROR);
        }
//        if(token.equals("undefined") )
//            return;
        if(tokenBlacklistService.isTokenBlacklisted(token)){
//            throw new AppException("token已注销");
             throw new AppException(ResultCode.FAILED_JWT_ERROR);
        }
        if(JwtUtils.isTokenExpired(token)){
//            throw new AppException("token已过期");
             throw new AppException(ResultCode.FAILED_JWT_ERROR);
        }
        String subject = JwtUtils.getSubjectFromToken(token);
        LoginUser loginUser;
        if(subject != null){
            loginUser = JSON.parseObject(subject, LoginUser.class);
        }else {
//            throw new AppException("subject为空");
             throw new AppException(ResultCode.FAILED_JWT_ERROR);
        }
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser,null,loginUser.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        log.info("用户{}登录成功,权限为{}",loginUser.getUsername(),loginUser.getAuthorities());
    }
}
